/*******************************************************************************
* Copyright (C) 2023
* @file      app_init.c
* @author    zhang
* @version   1.0.0.1
* @date      2023/10/26
* @brief     
* details.
* 
* change history
* <date>      | <version>   | <author>      | <description>
* 2023/10/26  | 1.0.0.1     | zhang         | create file
*
*******************************************************************************/
#include "app_includes.h"
#include "common.h"

//static uint8_t txBuff[280];
//static uint16_t txBuffLen;

int32_t commApplyResponse(CommApply *comm_apply, uint8_t *data, uint16_t len);

int32_t protocol_decode(CommApply *comm_apply, uint8_t *data, uint16_t len)
{
    uint16_t crc;
    if(len<6)
        return -1;
    if(data[0]!=0x55 || data[1]!=data[2] || data[3]!=0x55 || data[len-1]!=0xAA || data[1]!=len-6)
        return -2;
    if(check8BitSum(&data[4],data[1])!=data[len-2])
        return -3;
    return commApplyResponse(comm_apply, data+4, data[1]);
}

void protocol_send(CommApply *comm_apply, uint8_t *data, uint16_t len)
{
    uint16_t crc;
    comm_apply->tx_buff[0] = 0x55;
    comm_apply->tx_buff[1] = len;
    comm_apply->tx_buff[2] = len;
    comm_apply->tx_buff[3] = 0x55;
    //应用数据已经写入
    
    comm_apply->tx_buff[4+len] = check8BitSum(data, len);
    comm_apply->tx_buff[5+len] = 0xaa;
    comm_apply->tx_buff_len = len+6;
    
    board_uart_send(0, comm_apply->tx_buff, comm_apply->tx_buff_len);
}

void commApplyInit(CommApply *comm_apply, uint8_t *tx_buff)
{
    comm_apply->dataSendLenMax = 240;
    comm_apply->tx_buff = tx_buff;
    comm_apply->buff = &tx_buff[4];
}

void comm_master_apply_send(CommApply *comm_apply, uint8_t curr_page)
{
    int16_t len;
    comm_apply->header.cmd.master = 1;
    comm_apply->header.totalPage = (comm_apply->tx_dataLen+comm_apply->dataSendLenMax-1)/comm_apply->dataSendLenMax;
    comm_apply->header.currentPage = curr_page;
    if(comm_apply->header.totalPage>1) {//是多页数据
        comm_apply->header.cmd.muti_page = 1;
        if(curr_page==1)
            comm_apply->tx_send_data_len = 0;
        len = comm_apply->tx_dataLen - comm_apply->tx_send_data_len;
        if(len<0) return;
        if(len>comm_apply->dataSendLenMax) 
            len = comm_apply->dataSendLenMax;
        memcpy(comm_apply->buff,&comm_apply->header, sizeof(ApplyDataHeader));
        memcpy(comm_apply->buff+sizeof(ApplyDataHeader),comm_apply->data+comm_apply->tx_send_data_len, len);
        comm_apply->tx_curr_send_len = len + sizeof(ApplyDataHeader);
    }   
    else {
        comm_apply->header.cmd.muti_page = 0;
        memcpy(comm_apply->buff,&comm_apply->header, 2); //只要前3位数据
        if(comm_apply->tx_dataLen) {
            memcpy(&comm_apply->buff[2],&comm_apply->data, comm_apply->tx_dataLen);
            comm_apply->tx_curr_send_len = 2 + comm_apply->tx_dataLen;
        }else {
            comm_apply->buff[2] = comm_apply->header.currentPage;
        comm_apply->tx_curr_send_len = 3;
        }
            
    }
    protocol_send(comm_apply, comm_apply->buff, comm_apply->tx_curr_send_len);
}

int32_t commApplyResponse(CommApply *comm_apply, uint8_t *data, uint16_t len)
{
    ApplyDataHeader *recv_header = (ApplyDataHeader *)data;
    if(len<2 || (recv_header->cmd.function!=comm_apply->header.cmd.function&&recv_header->cmd.function!=0xff))
        return ApplyResultNoUse;
    if(recv_header->cmd.err)
        return ApplyResultFailure;
    if(recv_header->cmd.muti_page)
    {
        if(recv_header->currentPage==1)
            comm_apply->rx_dataLen = 0;
        memcpy(comm_apply->data + comm_apply->rx_dataLen, data + sizeof(ApplyDataHeader), len-sizeof(ApplyDataHeader));
        comm_apply->rx_dataLen += len-sizeof(ApplyDataHeader);
        if(recv_header->currentPage<recv_header->totalPage) //还有下一帧
        {
            //header.totalPage = recv_header->totalPage;
            comm_master_apply_send(comm_apply, comm_apply->header.currentPage+1); //接收下一帧数据
            return ApplyResultWait;
        }
        else
            comm_apply->rx_data = comm_apply->data;
    }
    else
    {
        comm_apply->rx_data = data + 2; //直接指定数据位置
        //memcpy(comm_apply->rx_data, (char *)&data[2], len-2);
        comm_apply->rx_dataLen = len-2;
    }

    if(comm_apply->header.totalPage>comm_apply->header.currentPage) //数据没发完
    {
        comm_master_apply_send(comm_apply, comm_apply->header.currentPage+1); //继续发送下一帧数据
        return ApplyResultWait;
    }

    switch(recv_header->cmd.function)
    {
    case ApplyCmdReadInfo:
        break;
    case ApplyCmdReadMeter:
        app_slave_dev_mht.change_flag.value = comm_apply->rx_data[0];
        memcpy(&app_slave_dev_mht.meter[0], &comm_apply->rx_data[1], comm_apply->rx_dataLen-1);
        break;
    case ApplyCmdReadSignal:

        break;
    case ApplyCmdReadSample:

        break;
    case ApplyCmdReadMap:

        break;
    case ApplyCmdReadPID:

        break;
    case ApplyCmdWriteMap:
    case ApplyCmdWritePID:
    case ApplyCmdWritePara:
        break;
    case ApplyCmdReadPara:
    {
        switch(recv_header->id)
        {
        case ApplyParaInfo:
            memcpy(&app_slave_dev_mht.para.info, &comm_apply->rx_data[0], sizeof(app_slave_dev_mht.para.info));
            break;
        case ApplyParaStore:
            memcpy(&app_slave_dev_mht.para.store, &comm_apply->rx_data[0], sizeof(app_slave_dev_mht.para.store));
            break;
        case ApplyParaRun:
            memcpy(&app_slave_dev_mht.para.run, &comm_apply->rx_data[0], sizeof(app_slave_dev_mht.para.run));
            break;
        case ApplyParaStatus:
            memcpy(&app_slave_dev_mht.para.status, &comm_apply->rx_data[0], sizeof(app_slave_dev_mht.para.status));
            break;
        }
        break;
    }
    case ApplyCmdReadWave:
    {

        break;
    }
    case ApplyCmdReadPIDValue:
    {

        break;
    }
    default:
        return ApplyResultNoUse;
        break;
    }
    return ApplyResultOK;
}


void comm_master_apply_readData(CommApply *comm_apply, uint8_t cmd, uint8_t id)
{
    comm_apply->tx_dataLen = 0;
    comm_apply->header.id = id;
    comm_apply->header.cmd.cmd = cmd;
    comm_master_apply_send(comm_apply, 1);
}

void comm_master_apply_writePara(CommApply *comm_apply, uint8_t id)
{
    comm_apply->header.id = id;
    switch(id) {
    case ApplyParaRun:
        comm_apply->header.cmd.cmd = ApplyCmdWritePara;
        comm_apply->tx_dataLen = sizeof(app_slave_dev_mht.para.run);
        memcpy(comm_apply->data, &app_slave_dev_mht.para.run, comm_apply->tx_dataLen);
        comm_master_apply_send(comm_apply, 1);
        break;
    }
}
